package elastic

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/elastic/go-elasticsearch/v7"
	"github.com/elastic/go-elasticsearch/v7/esapi"
	"github.com/elastic/go-elasticsearch/v7/esutil"
	"io"
	"peilian-api/app/global/variable"
	"strings"
)

func NewEsClient() *Elasticsearch {
	var esClient Elasticsearch
	c, err := esClient.Connect()
	if err != nil {
		fmt.Println(err.Error())
		return nil
	}
	esClient.Client = c
	return &esClient
}

type QueryBody struct {
	Query       *Query                  `json:"query,omitempty"`
	Size        *int                    `json:"size,omitempty"`
	Aggregation map[string]*Aggregation `json:"aggs,omitempty"`
}

type Elasticsearch struct {
	*elasticsearch.Client
	queryBody *QueryBody
}

func (e *Elasticsearch) Connect() (*elasticsearch.Client, error) {
	cfg := elasticsearch.Config{
		Addresses: []string{
			fmt.Sprintf("http://%s:%d", variable.Config.Elasticsearch.Host, variable.Config.Elasticsearch.Port),
		},
		Username: variable.Config.Elasticsearch.UserName,
		Password: variable.Config.Elasticsearch.Password,
	}
	es, err := elasticsearch.NewClient(cfg)
	if err != nil {
		return nil, err
	}
	if e.queryBody == nil {
		e.queryBody = &QueryBody{}
	}
	return es, nil
}

func (e *Elasticsearch) Query(query *Query) *Elasticsearch {
	if query == nil {
		e.queryBody.Query = NewMatchAllQuery()
		return e
	}
	e.queryBody.Query = query
	return e
}

func (e *Elasticsearch) Size(size int) *Elasticsearch {
	e.queryBody.Size = &size
	return e
}

func (e *Elasticsearch) Aggregation(name string, aggregation *Aggregation) *Elasticsearch {
	if e.queryBody.Aggregation == nil {
		e.queryBody.Aggregation = make(map[string]*Aggregation)
	}
	e.queryBody.Aggregation[name] = aggregation
	return e
}

func (e *Elasticsearch) Search(index ...string) ([]byte, error) {
	if index == nil || len(index) == 0 {
		index = []string{variable.Config.Elasticsearch.Index}
	}
	r, _ := json.Marshal(e.queryBody)
	sr := string(r)
	fmt.Println(sr)
	req := esapi.SearchRequest{
		Index: index,
		Body:  esutil.NewJSONReader(e.queryBody),
	}
	res, err := req.Do(context.Background(), e.Client)
	if err != nil {
		return nil, err
	}
	defer res.Body.Close()
	body, err := io.ReadAll(res.Body)
	if err != nil {
		return nil, err
	}
	return body, nil
}

// InitESIndex 初始化索引
func init() {
	// todo 跳过ES初始化索引操作
	fmt.Println("进来 -> 初始化Es索引操作....")
	return
	// 判断索引是否存在
	es := NewEsClient()
	//response, err := es.Indices.Delete([]string{variable.Config.Elasticsearch.Index, variable.Config.Elasticsearch.LabelIndex})
	//fmt.Println("delete index >> ", response.String(), err)

	existsRes, err := es.Indices.Exists([]string{variable.Config.Elasticsearch.Index})
	if err != nil {
		panic(fmt.Sprintf("check index exists error:%+v", err))
	}
	defer existsRes.Body.Close()
	fmt.Println("create index 1 >> ", existsRes.StatusCode)
	if existsRes.StatusCode == 404 {
		// 创建索引
		index := `
{
    "settings":
    {
        "number_of_shards": "3",
        "number_of_replicas": "0"
    },
    "mappings":
    {
        "properties":
        {
            "profession":
            {
                "eager_global_ordinals": true,
                "type": "keyword"
            },
            "education":
            {
                "type": "text",
                "fields":
                {
                    "keyword":
                    {
                        "ignore_above": 256,
                        "type": "keyword"
                    }
                }
            },
            "agent_id":
            {
                "type": "long"
            },
            "train_at":
            {
                "type": "long"
            },
            "user_name":
            {
                "type": "text"
            },
            "session_id":
            {
                "type": "long"
            },
            "emphasis_score":
            {
                "type": "long"
            },
            "career_name":
            {
                "eager_global_ordinals": true,
                "type": "keyword"
            },
            "express_score":
            {
                "type": "long"
            },
            "career_id":
            {
                "type": "long"
            },
            "logic_score":
            {
                "type": "long"
            },
            "score":
            {
                "type": "float"
            },
            "user_type":
            {
                "type": "keyword"
            },
            "school":
            {
                "eager_global_ordinals": true,
                "type": "keyword"
            },
            "user_id":
            {
                "type": "long"
            },
            "grade":
            {
                "eager_global_ordinals": true,
                "type": "keyword"
            },
            "academy":
            {
                "eager_global_ordinals": true,
                "type": "keyword"
            }
        }
    }
}
`
		response, err := es.Indices.Create(
			variable.Config.Elasticsearch.Index,
			es.Indices.Create.WithBody(strings.NewReader(index)),
		)
		if err != nil {
			panic(fmt.Sprintf("create index 1 error:%+v", err))
		}
		fmt.Printf("create index 1 result:%+v\n", response.String())
	}
	es = NewEsClient()
	existsRes2, err := es.Indices.Exists([]string{variable.Config.Elasticsearch.LabelIndex})
	if err != nil {
		panic(fmt.Sprintf("check index2 exists error:%+v", err))
	}
	defer existsRes2.Body.Close()
	fmt.Println("create index 2 >> ", existsRes2.StatusCode)
	if existsRes2.StatusCode == 404 {
		// 创建索引
		index := `
{
    "settings":
    {
        "number_of_shards": "3",
        "number_of_replicas": "0"
    },
    "mappings":
    {
        "properties":
        {
            "score":
            {
                "type": "float"
            },
            "user_id":
            {
                "type": "long"
            },
            "session_id":
            {
                "type": "long"
            },
            "label":
            {
                "eager_global_ordinals": true,
                "type": "keyword"
            },
            "type":
            {
                "type": "keyword"
            }
        }
    }
}
`
		response, err := es.Indices.Create(
			variable.Config.Elasticsearch.LabelIndex,
			es.Indices.Create.WithBody(strings.NewReader(index)),
		)
		if err != nil {
			panic(fmt.Sprintf("create index 2 error:%+v", err))
		}
		fmt.Printf("create index 2 result:%+v\n", response.String())

	}
}
